package cn.wanho.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.wanho.dao.CmsExamMapper;
import cn.wanho.dto.CmsExamCount;
import cn.wanho.rvo.*;
import cn.wanho.service.ExamService;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

@Service
public class ExamServiceImpl implements ExamService {

    private final String EXAM = "wanhocms:exam:paper:";
    private final String ANSWER_EXAM = "wanhocms:exam:answerpaper:";
    private final String FINALEXAM = "finish:exam";

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private CmsExamMapper cmsExamMapper;

    /**
     * 检测当前学生是否存在考试
     *
     * @return
     */
    @Override
    public ResultVO testCheck(Integer userId) throws JsonProcessingException {

        List<TestCheckVO> testCheckVOS = cmsExamMapper.testCheck(userId);
        if (testCheckVOS == null) {
            return ResultVO.failure(ResultEnum.TEST_EXIST_FAILURE.getResCode(), ResultEnum.TEST_EXIST_FAILURE.getResMsg());
        } else {
            List<TestCheckVVO> list = new ArrayList<>();
            for (TestCheckVO testCheckVO : testCheckVOS) {
                Date startTime = testCheckVO.getStartTime();
                String start = DateUtil.format(startTime, "yyyy-MM-dd hh:mm:ss");
                Date endTime = testCheckVO.getEndTime();
                String end = DateUtil.format(endTime, "yyyy-MM-dd hh:mm:ss");
                TestCheckVVO testCheckVVO = new TestCheckVVO(testCheckVO.getStageExamName(), start, end);
                list.add(testCheckVVO);
            }
            return ResultVO.success(ResultEnum.TEST_EXIST_SUCCESS.getResCode(), ResultEnum.TEST_EXIST_SUCCESS.getResMsg(), testCheckVOS);
        }
    }

    /**
     * 开始考试，展示试卷
     */
    @Override
    public ResultVO testing(Integer paperId,Integer id) {
        String key = "wanhocms:exam:paper:"+paperId+":object";
        String key1 = "wanhocms:exam:paper:"+paperId+":subject";
        //试卷所有题
        List<Object> list = new ArrayList<>();
        //选择题
        List<ChooseVO> chooses = cmsExamMapper.choose(paperId);
        if (!chooses.isEmpty()) {
            for (ChooseVO choose : chooses) {
                System.out.println("............................."+choose);
                redisTemplate.opsForZSet().add(key, choose,choose.getSort());
                list.add(choose);
            }
        }
        //填空题
        List<QuestionVO> blank = cmsExamMapper.blank(paperId);
        if (!blank.isEmpty()){
            for (QuestionVO questionVO : blank) {
                redisTemplate.opsForZSet().add(key, questionVO,questionVO.getSort());
                list.add(questionVO);
            }
        }
        //判断题
        List<QuestionVO> judge = cmsExamMapper.judge(paperId);
        if (!judge.isEmpty()){
            for (QuestionVO questionVO : judge) {
                redisTemplate.opsForZSet().add(key, questionVO,questionVO.getSort());
                list.add(questionVO);
            }
        }
        //程序题
        List<QuestionVO> program = cmsExamMapper.program(paperId);
        if (!program.isEmpty()){
            for (QuestionVO questionVO : program) {
                redisTemplate.opsForZSet().add(key1, questionVO,questionVO.getSort());
                list.add(questionVO);
            }
        }
        if (!list.isEmpty()){
            return ResultVO.success(ResultEnum.TEST_START_SUCCESS.getResCode(), ResultEnum.TEST_START_SUCCESS.getResMsg(), list);
        }else {
            return ResultVO.failure(ResultEnum.TEST_START_FAILURE.getResCode(), ResultEnum.TEST_START_FAILURE.getResMsg());
        }
    }

    /**
     * 保存当前答题（redis存储）
     *
     * @param questionId
     * @param answerContent
     * @param paperId
     * @param userId
     * @return
     */
   /* @Override
    public ResultVO saveExam(String questionId, String answerContent, String paperId, Integer userId) {
        String key = EXAM + userId + paperId + ":choose";
        String key1 = EXAM + userId + paperId + ":blank";
        String key2 = EXAM + userId + paperId + ":judge";
        String key3 = EXAM + userId + paperId + ":program";
        //试卷所有题
        List<Object> list = new ArrayList<>();
        //选择题
        List<ChooseVO> chooses = cmsExamMapper.choose(Integer.valueOf(paperId));
        if (!chooses.isEmpty()) {
            for (ChooseVO choose : chooses) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, choose.getSort(), choose.getId(), answerContent);
                redisTemplate.opsForZSet().add(key, redisExamVO, choose.getSort());
                list.add(choose);
            }
        }
        //填空题
        List<QuestionVO> blank = cmsExamMapper.blank(Integer.valueOf(paperId));
        if (!blank.isEmpty()) {
            for (QuestionVO questionVO : blank) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, questionVO.getSort(), questionVO.getId(), answerContent);
                redisTemplate.opsForZSet().add(key1, redisExamVO, questionVO.getSort());
                list.add(questionVO);
            }
        }
        //判断题
        List<QuestionVO> judge = cmsExamMapper.judge(Integer.valueOf(paperId));
        if (!judge.isEmpty()) {
            for (QuestionVO questionVO : judge) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, questionVO.getSort(), questionVO.getId(), answerContent);
                redisTemplate.opsForZSet().add(key2, redisExamVO, questionVO.getSort());
                list.add(questionVO);
            }
        }
        //程序题
        List<QuestionVO> program = cmsExamMapper.program(Integer.valueOf(paperId));
        if (!program.isEmpty()) {
            for (QuestionVO questionVO : program) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, questionVO.getSort(), questionVO.getId(), answerContent);
                redisTemplate.opsForZSet().add(key2, redisExamVO, questionVO.getSort());
                list.add(questionVO);
            }
        }
        if (!list.isEmpty()) {
            return ResultVO.success(ResultEnum.QUESTION_SAVE_SUCCESS.getResCode(), ResultEnum.QUESTION_SAVE_SUCCESS.getResMsg(), list);
        } else {
            return ResultVO.failure(ResultEnum.QUESTION_SAVE_FAILURE.getResCode(), ResultEnum.QUESTION_SAVE_FAILURE.getResMsg());
        }
    }*/

    /**
     * 考试结束提交试卷
     *
     * @param paperId
     * @param userId
     * @return
     */
    @Override
    public ResultVO commit(Integer userId,String paperId) {
        String key1 = ANSWER_EXAM + paperId + ":" + userId + ":object";
        String key2 = ANSWER_EXAM + paperId + ":" + userId + ":subject";
        String key3 = EXAM + paperId + ":object";
        String key4 = EXAM + paperId + ":subject";
        int count = 0;
        int fraction = 0;
        List<CmsExamCount> keys = new ArrayList<>(redisTemplate.opsForZSet().range(key1,0,-1));
        List<ChooseVO> keys1 = new ArrayList<>(redisTemplate.opsForZSet().range(key3,0,-1));
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < keys.size(); i++) {
            String answerContent = keys.get(i).getContent();
            String answer = keys1.get(i).getAnswer();
            if (answer.equals(answerContent)) {
                Integer value = keys1.get(i).getValue();
                count=value+count;
                keys.get(i).setScore(value);
                Double score = redisTemplate.opsForZSet().score(key3, keys1.get(i));
                redisTemplate.opsForZSet().removeRangeByScore(key1,score,score);
                redisTemplate.opsForZSet().add(key1,keys.get(i),score);
            }else{
                keys.get(i).setScore(0);
                Double score = redisTemplate.opsForZSet().score(key3, keys1.get(i));
                redisTemplate.opsForZSet().removeRangeByScore(key1,score,score);
                redisTemplate.opsForZSet().add(key1,keys.get(i),score);
            }
            //fraction = keys1.get(i).getValue() * count;
        }
        list.add(count);
        return ResultVO.success(ResultEnum.TEST_COMMIT_SUCCESS.getResCode(), ResultEnum.TEST_COMMIT_SUCCESS.getResMsg(), list);
    }

    @Override
    public ResultVO saveExam2(String questionId, String answerContent, String paperId, Integer userId) throws IllegalAccessException {

        String key1 = ANSWER_EXAM + paperId + ":" + userId + ":object";
        String key2 = ANSWER_EXAM + paperId + ":" + userId + ":subject";
        String key3 = EXAM + paperId + ":object";
        String key4 = EXAM + paperId + ":subject";
        CmsExamCount cmsExamCount = new CmsExamCount();
        Set set1 = redisTemplate.opsForZSet().reverseRangeByScore(key3, Integer.parseInt(questionId), Integer.parseInt(questionId));
        Set set2 = redisTemplate.opsForZSet().reverseRangeByScore(key4, Integer.parseInt(questionId), Integer.parseInt(questionId));
        Set set = (set1.isEmpty())?set2:set1;
        String key = (set1.isEmpty())?key2:key1;
        for (Object o : set) {
            Field[] fields = o.getClass().getDeclaredFields();
            for (Field field : fields) {
                String name = field.getName();
                field.setAccessible(true);
                Object resultValue = field.get(o);
                if ("id".equals(name)) {
                    cmsExamCount.setChoiceTopicId((Integer) resultValue);
                }
            }
        }
        cmsExamCount.setStudentId(userId);
        cmsExamCount.setContent(answerContent);
        redisTemplate.opsForZSet().add(key, cmsExamCount, Integer.parseInt(questionId));
        return ResultVO.success(ResultEnum.QUESTION_SAVE_SUCCESS.getResCode(), ResultEnum.QUESTION_SAVE_SUCCESS.getResMsg());
    }

    /**
     * 展示题目
     *
     * @param paperId
     */
    @Override
    public ResultVO showPaper(Integer paperId,Integer sort,Integer studentId) throws NoSuchFieldException, IllegalAccessException {
        String getkey = "wanhocms:exam:paper:"+paperId+":object";
        String getkey1 = "wanhocms:exam:paper:"+paperId+":subject";

        String key = "wanhocms:exam:answerpaper:"+paperId+":"+studentId+":object";
        String key1 = "wanhocms:exam:answerpaper:"+paperId+":"+studentId+":subject";

        Set set = redisTemplate.opsForZSet().reverseRangeByScore(getkey, sort, sort);
        Set set1 = redisTemplate.opsForZSet().reverseRangeByScore(getkey1, sort, sort);
        set.addAll(set1);
        StudentAnswerVO studentAnswerVO = new StudentAnswerVO();
        for (Object o : set) {
            Field[] fields = o.getClass().getDeclaredFields();
            for(Field field: fields){
                String name = field.getName();
                field.setAccessible(true);
                Object resultValue = field.get(o);
                if ("sort".equals(name)){
                    studentAnswerVO.setSort((Integer) resultValue);
                }else if ("id".equals(name)){
                    studentAnswerVO.setId((Integer) resultValue);
                }else if ("content".equals(name)){
                    studentAnswerVO.setContent((String) resultValue);
                }else if ("isSingle".equals(name)){
                    studentAnswerVO.setIsSingle((Byte) resultValue);
                }
                System.out.println(name + ": " + resultValue);
            }
            System.out.println(studentAnswerVO);
        }

        Set set2 = redisTemplate.opsForZSet().reverseRangeByScore(key, sort, sort);
        Set set3 = redisTemplate.opsForZSet().reverseRangeByScore(key1, sort, sort);
        set2.addAll(set3);
        for (Object o : set2) {
            Field[] fields = o.getClass().getDeclaredFields();
            for (Field field : fields) {
                String name = field.getName();
                field.setAccessible(true);
                Object resultValue = field.get(o);
                if ("answerContent".equals(name)&& resultValue != null){
                    studentAnswerVO.setStudentAnswer((String) resultValue);
                }
            }
            System.out.println(studentAnswerVO);
        }

        return ResultVO.success(ResultEnum.SHOW_PAPER_SUCCESS.getResCode(), ResultEnum.SHOW_PAPER_SUCCESS.getResMsg(),studentAnswerVO);
    }

    /*public ResultVO saveExam2(String questionId, String answerContent, String paperId, Integer userId) {

        String key1 = ANSWER_EXAM + paperId+":"+userId+":object";
        String key2 = ANSWER_EXAM + paperId+":"+userId+":subject";
        String key3 = EXAM + paperId+":object";
        String key4 = EXAM + paperId+":subject";
       *//* String key1 = EXAM + userId + paperId + ":blank";
        String key2 = EXAM + userId + paperId + ":judge";
        String key3 = EXAM + userId + paperId + ":program";
        Set<ChooseVO> set1 = redisTemplate.opsForZSet().reverseRangeByScore(key, Integer.parseInt(questionId), Integer.parseInt(questionId));
        Set<QuestionVO> set2 = redisTemplate.opsForZSet().reverseRangeByScore(key1, Integer.parseInt(questionId), Integer.parseInt(questionId));
        Set<QuestionVO> set3 = redisTemplate.opsForZSet().reverseRangeByScore(key2, Integer.parseInt(questionId), Integer.parseInt(questionId));
        Set<QuestionVO> set4 = redisTemplate.opsForZSet().reverseRangeByScore(key3, Integer.parseInt(questionId), Integer.parseInt(questionId));
        System.out.println(set1.size());*//*

        if (!set1.isEmpty()){
            for (ChooseVO choose : set1) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, choose.getSort(), choose.getId(), answerContent);
                redisTemplate.opsForZSet().add(key,redisExamVO,Integer.parseInt(questionId));
            }
        }
        if (!set2.isEmpty()) {
            for (QuestionVO choose : set2) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, choose.getSort(), choose.getId(), answerContent);
                redisTemplate.opsForZSet().add(key, redisExamVO, Integer.parseInt(questionId));
            }
        }
        if (!set3.isEmpty()) {
            for (QuestionVO choose : set3) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, choose.getSort(), choose.getId(), answerContent);
                redisTemplate.opsForZSet().add(key, redisExamVO, Integer.parseInt(questionId));
            }
        }
        if (!set4.isEmpty()) {
            for (QuestionVO choose : set4) {
                RedisExamVO redisExamVO = new RedisExamVO(userId, choose.getSort(), choose.getId(), answerContent);
                redisTemplate.opsForZSet().add(key, redisExamVO, Integer.parseInt(questionId));
            }
        }
        return ResultVO.failure(ResultEnum.QUESTION_SAVE_FAILURE.getResCode(),ResultEnum.QUESTION_SAVE_FAILURE.getResMsg());
    }*/

    /*@Override
    public ResultVO commit(String paperId, Integer userId) {
        int count = 0;
        int fraction = 0;
        List<RedisExamVO> keys = (List<RedisExamVO>) redisTemplate.keys(EXAM + userId + paperId + "choose");
        List<ChooseVO> keys1 = (List<ChooseVO>) redisTemplate.keys("cms:exam:" + userId + ":" + paperId + ":choose");
        List<Object> list = new ArrayList<>();
        for (int i = 0; i < keys.size(); i++) {
            String answerContent = keys.get(i).getAnswerContent();
            String answer = keys1.get(i).getAnswer();
            if (answer.equals(answerContent)) {
                count++;
            }
            fraction = keys1.get(i).getValue() * count;
            keys.get(i).setScore(String.valueOf(fraction));
        }
        list.add(count);
        return ResultVO.success(ResultEnum.TEST_COMMIT_SUCCESS.getResCode(), ResultEnum.TEST_COMMIT_SUCCESS.getResMsg(), list);
    }*/
}
